package middleware

import (
	"errors"
	"goravel/app/models"
	"goravel/app/scopes"
	"goravel/constants"
	"goravel/utils/response"

	"github.com/goravel/framework/auth"
	"github.com/goravel/framework/contracts/http"
	"github.com/goravel/framework/facades"
)

func Authenticate() http.Middleware {
	return func(ctx http.Context) {

		facades.Log().Info("获取用户token")

		// 从请求头中获取 Authorization 令牌
		token := ctx.Request().Header("Authorization", "")
		ctx.WithValue(constants.TokenPrefix, token)
		if token == "" {
			response.Abort(ctx, http.StatusUnauthorized, "Unauthorized.")
			return
		}

		// 解析令牌
		payload, err := facades.Auth(ctx).Parse(token)
		if err != nil {
			// facades.Log().Error("Failed to parse token: ", err)
			response.Abort(ctx, http.StatusUnauthorized, "Invalid token.")
			return
		}

		if errors.Is(err, auth.ErrorTokenExpired) {
			response.Abort(ctx, http.StatusUnauthorized, "Error token expired.")
			return
		}

		var user models.User

		if err := scopes.Query(ctx).FindOrFail(&user, payload.Key); err != nil {
			response.Abort(ctx, http.StatusUnauthorized, facades.Lang(ctx).Get("errors.failed_to_fetch"))
			return
		}

		newToken, err := facades.Auth(ctx).Guard(payload.Guard).LoginUsingID(user.ID)
		if err != nil {
			response.Abort(ctx, http.StatusUnauthorized, "生成 Token 失败.")
			return
		}

		ctx.WithValue("user", user)

		ctx.WithValue(constants.TokenPrefix, newToken)

		ctx.Request().Next()
	}
}
